package auth

import (
	"errors"
	"x-admin/backend/pkg/jwt"
	"x-admin/backend/pkg/utils"
	"x-admin/backend/pkg/xerror"

	"gorm.io/gorm"
)

// Service 认证业务逻辑层接口
type Service interface {
	Login(req *LoginRequest) (*LoginResponse, error)
	GetUserInfo(userID uint) (*UserInfo, error)
	ChangePassword(userID uint, req *ChangePasswordRequest) error
	UpdateProfile(userID uint, req *UpdateProfileRequest) (*UserInfo, error)
	Logout(userID uint) error
	GetUserMenus(userID uint) ([]*MenuInfo, error)
	GetUserPermissions(userID uint) ([]string, error)
}

// service 认证业务逻辑层实现
type service struct {
	repo Repository
}

// NewService 创建认证业务逻辑层
func NewService(repo Repository) Service {
	return &service{
		repo: repo,
	}
}

// Login 用户登录
func (s *service) Login(req *LoginRequest) (*LoginResponse, error) {
	// 根据用户名查找用户
	user, err := s.repo.GetUserByUsername(req.Username)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("用户名或密码错误")
		}
		return nil, err
	}

	// 检查用户状态
	if user.Status != 1 {
		return nil, errors.New("用户已被禁用")
	}

	// 验证密码
	if !utils.CheckPassword(req.Password, user.Password) {
		return nil, errors.New("用户名或密码错误")
	}

	// 生成JWT令牌
	token, expiresAt, err := jwt.GenerateToken(user.ID, user.Username)
	if err != nil {
		return nil, errors.New("生成令牌失败")
	}

	// 更新最后登录时间
	if err := s.repo.UpdateLastLogin(user.ID); err != nil {
		// 记录日志，但不影响登录流程
	}

	// 构造响应
	response := &LoginResponse{
		Token:     token,
		ExpiresAt: expiresAt,
		User: UserInfo{
			ID:       user.ID,
			Username: user.Username,
			Nickname: user.Nickname,
			Email:    user.Email,
			Phone:    user.Phone,
			Avatar:   user.Avatar,
			Status:   user.Status,
		},
	}

	return response, nil
}

// GetUserInfo 获取用户信息
func (s *service) GetUserInfo(userID uint) (*UserInfo, error) {
	user, err := s.repo.GetUserByID(userID)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("用户不存在")
		}
		return nil, err
	}

	userInfo := &UserInfo{
		ID:       user.ID,
		Username: user.Username,
		Nickname: user.Nickname,
		Email:    user.Email,
		Phone:    user.Phone,
		Avatar:   user.Avatar,
		Status:   user.Status,
	}

	return userInfo, nil
}

// ChangePassword 修改密码
func (s *service) ChangePassword(userID uint, req *ChangePasswordRequest) error {
	// 获取用户信息
	user, err := s.repo.GetUserByID(userID)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return xerror.New("用户不存在")
		}
		return err
	}

	// 验证原密码
	if !utils.CheckPassword(req.OldPassword, user.Password) {
		return xerror.New("原密码错误")
	}

	// 加密新密码
	hashedPassword, err := utils.HashPassword(req.NewPassword)
	if err != nil {
		return errors.New("密码加密失败")
	}

	// 更新密码
	user.Password = hashedPassword
	if err := s.repo.UpdateUser(user); err != nil {
		return errors.New("密码更新失败")
	}

	return nil
}

// UpdateProfile 更新个人信息
func (s *service) UpdateProfile(userID uint, req *UpdateProfileRequest) (*UserInfo, error) {
	// 获取用户信息
	user, err := s.repo.GetUserByID(userID)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("用户不存在")
		}
		return nil, err
	}

	// 更新字段
	if req.Nickname != nil {
		user.Nickname = *req.Nickname
	}

	if req.Email != nil {
		// 检查邮箱是否已被使用（仅当邮箱不为空时检查）
		if *req.Email != "" {
			existingUser, err := s.repo.GetUserByEmail(*req.Email)
			if err == nil && existingUser.ID != userID {
				return nil, errors.New("邮箱已被使用")
			}
		}
		user.Email = *req.Email
	}

	if req.Phone != nil {
		user.Phone = *req.Phone
	}

	if req.Avatar != nil {
		user.Avatar = *req.Avatar
	}

	// 保存更新
	if err := s.repo.UpdateUser(user); err != nil {
		return nil, errors.New("更新失败")
	}

	// 返回更新后的用户信息
	userInfo := &UserInfo{
		ID:       user.ID,
		Username: user.Username,
		Nickname: user.Nickname,
		Email:    user.Email,
		Phone:    user.Phone,
		Avatar:   user.Avatar,
		Status:   user.Status,
	}

	return userInfo, nil
}

// Logout 用户登出
func (s *service) Logout(userID uint) error {
	// 这里可以实现令牌黑名单等逻辑
	// 目前只是简单返回成功
	return nil
}

// GetUserMenus 获取用户菜单
func (s *service) GetUserMenus(userID uint) ([]*MenuInfo, error) {
	return s.repo.GetUserMenus(userID)
}

// GetUserPermissions 获取用户权限
func (s *service) GetUserPermissions(userID uint) ([]string, error) {
	return s.repo.GetUserPermissions(userID)
}
